package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    @Cacheable(value = CacheConstant.RESOURCE_LIST ,key ="#resourceDto.hashCode()")
    public List<ResourceVo> resourceList(ResourceDto resourceDto) {

        List<Resource> list=resourceMapper.getList(resourceDto);
        List<ResourceVo> resourceVos = BeanUtil.copyToList(list, ResourceVo.class);
        return resourceVos;
    }

    @Override
    @Cacheable(value = CacheConstant.RESOURCE_TREE )
    public TreeVo resourceTree(ResourceDto resourceDto) {
        //一次查询所有的菜单数据（查询出根节点的所有子孙节点）
        //定义查询类
        ResourceDto dto = ResourceDto.builder()
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .dataState(SuperConstant.DATA_STATE_0).build();
        //根节点所有菜单信息
        List<Resource> resources = resourceMapper.getList(dto);
        //封装成树形结构
        ArrayList<TreeItemVo> treeItemVos = new ArrayList<>();
        //自定义根节点
        Resource resource = new Resource();
        resource.setResourceNo(SuperConstant.ROOT_PARENT_ID);
        resource.setResourceName("智慧养老院");
        //调用方法递归获取值
        recursionTreeItem(treeItemVos,resource,resources);
        //返回TreeVo
        return TreeVo.builder().items(treeItemVos).build();
    }

    @Override
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    public void creatResource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //查询父类资源
        Resource parentResource =resourceMapper.selectResourceNo(resourceDto.getParentResourceNo());
        //设置实体类的数据状态 为父类资源状态
        resource.setDataState(parentResource.getDataState());
        //判断 当前新增的资源是否为菜单
        boolean isMenu=true;
        if(SuperConstant.BUTTON.equals(resource.getResourceType())){
            isMenu=false;
        }
        //生成编码资源
        String resourceNo=creatResourceNo(resource.getParentResourceNo(),isMenu);
        resource.setResourceNo(resourceNo);
        resourceMapper.insert(resource);

    }

    @Override
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    public void update(ResourceDto resourceDto) {

        Resource bean = BeanUtil.toBean(resourceDto, Resource.class);
        resourceMapper.updateByPrimaryKeySelective(bean);
    }

    @Override
    @Transactional
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    public void updateStatus(ResourceDto resourceDto) {
        Resource parentResource=resourceMapper.getParent(resourceDto);
        String dataState = parentResource.getDataState();
        if(dataState.equals("1")){
            throw new BaseException(BasicEnum.PARENT_MENU_DISABLE);
        }
        resourceMapper.updateStatus(resourceDto);
        Resource resource = new Resource();
        resource.setParentResourceNo(NoProcessing.processString(resourceDto.getResourceNo()));
        resource.setDataState(resourceDto.getDataState());
        resourceMapper.updateStatusByParent(resource);
    }

    @Override
    @Transactional
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    public void delete(String resourceNo) {
        resourceMapper.delete(resourceNo);
        resourceMapper.deleteByParent(resourceNo);
    }

    @Override
    public List<MenuVo> menus(Long userId) {
        //查询数据
        List<MenuVo> menuVoList=resourceMapper.findResourceListByUserId(userId);
        if(ObjectUtil.isEmpty(menuVoList)){
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }
        //数据分组
        Map<String, List<MenuVo>> parentMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));
        //数据组装
        //遍历所有菜单对象，组装他们的子菜单
        menuVoList.forEach(menuVo -> {
            //根据前端代码的需要
            menuVo.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
            menuVo.setRedirect("/"+menuVo.getName());
            List<MenuVo> menuVos = parentMap.get(menuVo.getResourceNo());
            if(!ObjectUtil.isEmpty(menuVos)){
                menuVo.setChildren(menuVos);
            }
        });
        //返回一级菜单
        return parentMap.get(SuperConstant.ROOT_PARENT_ID);
    }

    private String creatResourceNo(String parentResourceNo, boolean isMenu) {
        //菜单最大是三级
        //根节点   100 001 000 000 000
        //一级菜单 100 001 001 000 000
        //二级菜单 100 001 001 001 000
        //三级菜单 100 001 001 001 001
        if(isMenu && NoProcessing.processString(parentResourceNo).length()/3>=5){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        //根据父资源编码 生成子资源编码
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        List<Resource> list = resourceMapper.getList(dto);
        if (ObjectUtil.isEmpty(list)) {
            return NoProcessing.createNo(parentResourceNo,false);
        }else{
            //获取父类子菜单中最大的编码
            String no = list.stream().map(s -> s.getResourceNo()).max((o1, o2) -> o1.compareTo(o2)).get();
            
            //根据最大编码生成该子类编码然后返回
            return  NoProcessing.createNo(no,true);
        }

    }

    private void recursionTreeItem(ArrayList<TreeItemVo> treeItemVos, Resource root, List<Resource> resources) {
        //根据当前节点 创建 TreeIemVo
        TreeItemVo treeItemVo = TreeItemVo.builder()
                .id(root.getResourceNo())
                .label(root.getResourceName()).build();
        //搞定children
        //筛选出当前节点的子菜单
        List<Resource> list = resources.stream()
                .filter(n -> n.getParentResourceNo().equals(root.getResourceNo()))
                .collect(Collectors.toList());
        //判断，递归赋值
        if (!ObjectUtil.isEmpty(list)) {
            ArrayList<TreeItemVo> childRenList = new ArrayList<>();
            list.forEach( resource ->recursionTreeItem(childRenList,resource,resources));
            treeItemVo.setChildren(childRenList);
        }
        //返回对象赋值
        treeItemVos.add(treeItemVo);
    }



}
